//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.ponly.fs.util;

import java.util.Arrays;

public abstract class Base64 {
    private static final int CHUNK_SIZE = 76;
    private static final char[] CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
    private static final char[] URL_SAFE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-".toCharArray();
    private static final int[] INV = new int[256];
    private static final int[] URL_SAFE_INV = new int[256];
    private static final char PADDING = '=';
    public static final byte[] EMPTY_BYTES = new byte[0];
    public static final char[] EMPTY_CHARS = new char[0];

    public static String encodeToUrlSafeString(byte[] bytes) {
        return encodeToUrlSafeString(bytes, false);
    }

    public static String encodeToUrlSafeString(byte[] bytes, boolean lineSep) {
        return String.valueOf(encodeToChars(bytes, lineSep, true));
    }

    public static String encodeToString(byte[] bytes) {
        return encodeToString(bytes, false);
    }

    public static String encodeToString(byte[] bytes, boolean lineSep) {
        return new String(encodeToChars(bytes, lineSep));
    }

    public static char[] encodeToChars(byte[] bytes, boolean lineSeparator) {
        return encodeToChars(bytes, lineSeparator, false);
    }

    public static byte[] encode(byte[] bytes) {
        return encode(bytes, false);
    }

    public static byte[] encode(byte[] bytes, boolean lineSeparator) {
        return encode(bytes, lineSeparator, false);
    }

    public static char[] encodeToChars(byte[] bytes, boolean lineSeparator, boolean urlSafe) {
        char[] TAB = urlSafe?URL_SAFE_CHARS:CHARS;
        int len = bytes != null?bytes.length:0;
        if(len == 0) {
            return EMPTY_CHARS;
        } else {
            int evenlen = len / 3 * 3;
            int cnt = (len - 1) / 3 + 1 << 2;
            int destLen = cnt + (lineSeparator?(cnt - 1) / 76 << 1:0);
            char[] dest = new char[destLen];
            int left = 0;
            int i = 0;
            int cc = 0;

            while(left < evenlen) {
                int i1 = (bytes[left++] & 255) << 16 | (bytes[left++] & 255) << 8 | bytes[left++] & 255;
                dest[i++] = TAB[i1 >>> 18 & 63];
                dest[i++] = TAB[i1 >>> 12 & 63];
                dest[i++] = TAB[i1 >>> 6 & 63];
                dest[i++] = TAB[i1 & 63];
                if(lineSeparator) {
                    ++cc;
                    if(cc == 19 && i < destLen - 2) {
                        dest[i++] = 13;
                        dest[i++] = 10;
                        cc = 0;
                    }
                }
            }

            left = len - evenlen;
            if(left > 0) {
                i = (bytes[evenlen] & 255) << 10 | (left == 2?(bytes[len - 1] & 255) << 2:0);
                dest[destLen - 4] = TAB[i >> 12];
                dest[destLen - 3] = TAB[i >>> 6 & 63];
                dest[destLen - 2] = left == 2?TAB[i & 63]:61;
                dest[destLen - 1] = 61;
            }

            return dest;
        }
    }

    public static byte[] encode(byte[] bytes, boolean lineSep, boolean urlSafe) {
        char[] TAB = urlSafe?URL_SAFE_CHARS:CHARS;
        int len = bytes != null?bytes.length:0;
        if(len == 0) {
            return EMPTY_BYTES;
        } else {
            int evenlen = len / 3 * 3;
            int cnt = (len - 1) / 3 + 1 << 2;
            int destlen = cnt + (lineSep?(cnt - 1) / 76 << 1:0);
            byte[] dest = new byte[destlen];
            int left = 0;
            int i = 0;
            int cc = 0;

            while(left < evenlen) {
                int i1 = (bytes[left++] & 255) << 16 | (bytes[left++] & 255) << 8 | bytes[left++] & 255;
                dest[i++] = (byte)TAB[i1 >>> 18 & 63];
                dest[i++] = (byte)TAB[i1 >>> 12 & 63];
                dest[i++] = (byte)TAB[i1 >>> 6 & 63];
                dest[i++] = (byte)TAB[i1 & 63];
                if(lineSep) {
                    ++cc;
                    if(cc == 19 && i < destlen - 2) {
                        dest[i++] = 13;
                        dest[i++] = 10;
                        cc = 0;
                    }
                }
            }

            left = len - evenlen;
            if(left > 0) {
                i = (bytes[evenlen] & 255) << 10 | (left == 2?(bytes[len - 1] & 255) << 2:0);
                dest[destlen - 4] = (byte)TAB[i >> 12];
                dest[destlen - 3] = (byte)TAB[i >>> 6 & 63];
                dest[destlen - 2] = left == 2?(byte)TAB[i & 63]:61;
                dest[destlen - 1] = 61;
            }

            return dest;
        }
    }

    public static byte[] decode(String base64) {
        return decode(base64, false);
    }

    public static byte[] decode(String base64, boolean urlSafe) {
        return decode(base64.toCharArray(), urlSafe);
    }

    public static byte[] decode(char[] base64Chars) {
        return decode(base64Chars, false);
    }

    public static byte[] decode(char[] base64Chars, boolean urlSafe) {
        int[] DECODE_TAB = urlSafe?URL_SAFE_INV:INV;
        int length = base64Chars.length;
        if(length == 0) {
            return EMPTY_BYTES;
        } else {
            int sndx = 0;
            int endx = length - 1;
            int pad = base64Chars[endx] == 61?(base64Chars[endx - 1] == 61?2:1):0;
            int cnt = endx - sndx + 1;
            int sepCnt = length > 76?(base64Chars[76] == 13?cnt / 76 + 2:0) << 1:0;
            int len = ((cnt - sepCnt) * 6 >> 3) - pad;
            byte[] dest = new byte[len];
            int d = 0;
            int i = 0;
            int r = len / 3 * 3;

            while(d < r) {
                int i1 = DECODE_TAB[base64Chars[sndx++]] << 18 | DECODE_TAB[base64Chars[sndx++]] << 12 | DECODE_TAB[base64Chars[sndx++]] << 6 | DECODE_TAB[base64Chars[sndx++]];
                dest[d++] = (byte)(i1 >> 16);
                dest[d++] = (byte)(i1 >> 8);
                dest[d++] = (byte)i1;
                if(sepCnt > 0) {
                    ++i;
                    if(i == 19) {
                        sndx += 2;
                        i = 0;
                    }
                }
            }

            if(d < len) {
                i = 0;

                for(r = 0; sndx <= endx - pad; ++r) {
                    i |= DECODE_TAB[base64Chars[sndx++]] << 18 - r * 6;
                }

                for(r = 16; d < len; r -= 8) {
                    dest[d++] = (byte)(i >> r);
                }
            }

            return dest;
        }
    }

    public static byte[] decode(byte[] base64Bytes) {
        return decode(base64Bytes, false);
    }

    public static byte[] decode(byte[] base64Bytes, boolean urlSafe) {
        int[] DECODE_TAB = urlSafe?URL_SAFE_INV:INV;
        int length = base64Bytes.length;
        if(length == 0) {
            return EMPTY_BYTES;
        } else {
            int sndx = 0;
            int endx = length - 1;
            int pad = base64Bytes[endx] == 61?(base64Bytes[endx - 1] == 61?2:1):0;
            int cnt = endx - sndx + 1;
            int sepCnt = length > 76?(base64Bytes[76] == 13?cnt / 78:0) << 1:0;
            int len = ((cnt - sepCnt) * 6 >> 3) - pad;
            byte[] dest = new byte[len];
            int d = 0;
            int i = 0;
            int r = len / 3 * 3;

            while(d < r) {
                int i1 = DECODE_TAB[base64Bytes[sndx++]] << 18 | DECODE_TAB[base64Bytes[sndx++]] << 12 | DECODE_TAB[base64Bytes[sndx++]] << 6 | DECODE_TAB[base64Bytes[sndx++]];
                dest[d++] = (byte)(i1 >> 16);
                dest[d++] = (byte)(i1 >> 8);
                dest[d++] = (byte)i1;
                if(sepCnt > 0) {
                    ++i;
                    if(i == 19) {
                        sndx += 2;
                        i = 0;
                    }
                }
            }

            if(d < len) {
                i = 0;

                for(r = 0; sndx <= endx - pad; ++r) {
                    i |= DECODE_TAB[base64Bytes[sndx++]] << 18 - r * 6;
                }

                for(r = 16; d < len; r -= 8) {
                    dest[d++] = (byte)(i >> r);
                }
            }

            return dest;
        }
    }

    private Base64() {
    }

    static {
        Arrays.fill(INV, -1);
        int i = 0;

        int iS;
        for(iS = CHARS.length; i < iS; INV[CHARS[i]] = i++) {
            ;
        }

        INV[61] = 0;
        Arrays.fill(URL_SAFE_INV, -1);
        i = 0;

        for(iS = URL_SAFE_CHARS.length; i < iS; URL_SAFE_INV[URL_SAFE_CHARS[i]] = i++) {
            ;
        }

        URL_SAFE_INV[61] = 0;
    }
}
